package Parmcfg;

import NetSDKDemo.HCNetSDK;
import com.sun.jna.Memory;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import util.LogManager;
import view.ScanCameraFrame;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import static Parmcfg.TestDemo.hCNetSDK;

/**
 * 设备维护管理
 *
 * @Author: jiangxin14
 * @Date: 2024-08-12  16:56
 */
public class DevManager {

    public static fRemoteConfigCallBack fDevStatusCallBack = null;


    /**
     * 手动获取设备在线状态
     *
     * @param iUserID
     */
    public static void getDeviceStatus(int iUserID) {
        boolean devStatus = hCNetSDK.NET_DVR_RemoteControl(iUserID, HCNetSDK.NET_DVR_CHECK_USER_STATUS, null, 0);
        if (!devStatus) {
            System.out.println("设备不在线");
            LogManager.getInstance().appendLog("设备不在线");
        } else {
            System.out.println("设备在线");
            LogManager.getInstance().appendLog("设备在线");
        }
    }

    /**
     * 获取设备工作状态，CPU，硬盘状态,通道状态，一般适用于硬盘录像机设备
     *
     * @param iUserID
     */
    public static void getWorkS(int iUserID) {

        HCNetSDK.NET_DVR_GETWORKSTATE_COND strWorkStatusCond = new HCNetSDK.NET_DVR_GETWORKSTATE_COND();
        strWorkStatusCond.read();
        strWorkStatusCond.dwSize = strWorkStatusCond.size(); //设置结构体大小
        strWorkStatusCond.byFindChanByCond = 0; //0- 查找全部通道，1- 根据dwFindChanNo数组中各元素所指定的有效通道号进行查找
        strWorkStatusCond.byFindHardByCond = 0; //0- 查找全部磁盘，1- 根据dwFindHardStatus数组中各元素所指定的有效硬盘号进行查找
        strWorkStatusCond.write();
        Pointer lpInBuffer = strWorkStatusCond.getPointer();
        Pointer pUser = null;
        if (fDevStatusCallBack == null) {
            fDevStatusCallBack = new fRemoteConfigCallBack();
        }
        int devStatus = hCNetSDK.NET_DVR_StartRemoteConfig(iUserID, HCNetSDK.NET_DVR_GET_WORK_STATUS_V50, lpInBuffer, strWorkStatusCond.size(),
                fDevStatusCallBack, pUser);

        if (devStatus <= -1) {
            System.err.println("获取设备状态NET_DVR_StartRemoteConfig建立失败,错误码：" + hCNetSDK.NET_DVR_GetLastError());
            return;
        }

        System.out.println("获取设备工作状态成功");
    }

    /**
     * 获取设备状态回调函数
     */
    static class fRemoteConfigCallBack implements HCNetSDK.FRemoteConfigCallBack {
        public void invoke(int dwType, Pointer lpBuffer, int dwBufLen, Pointer pUserData) {
            switch (dwType) {
                case HCNetSDK.NET_SDK_CALLBACK_TYPE_STATUS: {
                    HCNetSDK.BYTE_ARRAY struCallbackStatus = new HCNetSDK.BYTE_ARRAY(dwBufLen);
                    struCallbackStatus.write();
                    Pointer pStatus = struCallbackStatus.getPointer();
                    pStatus.write(0, lpBuffer.getByteArray(0, struCallbackStatus.size()), 0, dwBufLen);
                    struCallbackStatus.read();
//                    System.out.println(new String(struCallbackStatus.byValue));
                    break;
                }
                case HCNetSDK.NET_SDK_CALLBACK_TYPE_PROGRESS: {
                    HCNetSDK.BYTE_ARRAY struPrscess = new HCNetSDK.BYTE_ARRAY(dwBufLen);
                    struPrscess.write();
                    Pointer pStatus = struPrscess.getPointer();
                    pStatus.write(0, lpBuffer.getByteArray(0, struPrscess.size()), 0, dwBufLen);
                    struPrscess.read();
                    System.out.println("进度值：" + new String(struPrscess.byValue));
                    break;
                }
                case HCNetSDK.NET_SDK_CALLBACK_TYPE_DATA: {
                    HCNetSDK.NET_DVR_WORKSTATE_V40 strWorKStatus = new HCNetSDK.NET_DVR_WORKSTATE_V40();
                    strWorKStatus.read();
                    strWorKStatus.dwSize = strWorKStatus.size();
                    strWorKStatus.write();
                    Pointer lpOutBuffer = strWorKStatus.getPointer();
                    lpOutBuffer.write(0, lpBuffer.getByteArray(0, strWorKStatus.size()), 0, dwBufLen);
                    strWorKStatus.read();
                    System.out.println("设备状态：" + strWorKStatus.dwDeviceStatic);//0－正常；1－CPU占用率太高，超过85%；2－硬件错误，例如串口异常
                    System.out.println("第一个硬盘状态：硬盘容量：" + strWorKStatus.struHardDiskStatic[0].dwVolume + " 硬盘剩余容量：" + strWorKStatus.struHardDiskStatic[0].dwFreeSpace +
                            " 硬盘状态：" + strWorKStatus.struHardDiskStatic[0].dwHardDiskStatic);
                    System.out.println("第一路通道状态：是否录像：" + strWorKStatus.struChanStatic[0].byRecordStatic + " 信号连接状态：" + strWorKStatus.struChanStatic[0].bySignalStatic +
                            " 连接该通道的客户端个数：" + strWorKStatus.struChanStatic[0].dwLinkNum);
                    break;

                }
                default: {
                    break;
                }
            }
        }
    }


    //获取设备的基本参数
    public static void getDeviceInfo(int iUserID) {
        try {
            HCNetSDK.NET_DVR_DEVICECFG_V40 m_strDeviceCfg = new HCNetSDK.NET_DVR_DEVICECFG_V40();
            m_strDeviceCfg.dwSize = m_strDeviceCfg.size();
            m_strDeviceCfg.write();
            Pointer pStrDeviceCfg = m_strDeviceCfg.getPointer();
            IntByReference pInt = new IntByReference(0);
            boolean b_GetCfg = hCNetSDK.NET_DVR_GetDVRConfig(iUserID, HCNetSDK.NET_DVR_GET_DEVICECFG_V40,
                    0Xffffffff, pStrDeviceCfg, m_strDeviceCfg.dwSize, pInt);
            if (!b_GetCfg) {
                System.out.println("获取参数失败  错误码：" + hCNetSDK.NET_DVR_GetLastError() + " " + hCNetSDK.NET_DVR_GetLastError());
            }
            System.out.println("获取参数成功");
            m_strDeviceCfg.read();
            System.out.println("设备名称:" + new String(m_strDeviceCfg.sDVRName).trim() + "设备序列号：" + new String(m_strDeviceCfg.sSerialNumber).trim());
            System.out.println("模拟通道个数" + m_strDeviceCfg.byChanNum);
            parseVersion(m_strDeviceCfg.dwSoftwareVersion);
            parseBuildTime(m_strDeviceCfg.dwSoftwareBuildDate);
            parseDSPBuildDate(m_strDeviceCfg.dwDSPSoftwareBuildDate);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }


    public static void parseBuildTime(int buildTime) {
        int year = ((buildTime & 0XFF << 16) >> 16) + 2000;
        int month = (buildTime & 0XFF << 8) >> 8;
        int data = buildTime & 0xFF;
        System.out.println("Build:" + year + "." + month + "." + data);
    }

    public static void parseDSPBuildDate(int DSPBuildDate) {
        int year = ((DSPBuildDate & 0XFF << 16) >> 16) + 2000;
        int month = (DSPBuildDate & 0XFF << 8) >> 8;
        int data = DSPBuildDate & 0xFF;
        System.out.println("DSPBuildDate:" + year + "." + month + "." + data);
    }

    //设备版本解析
    public static void parseVersion(int version) {
        int firstVersion = (version & 0XFF << 24) >> 24;
        int secondVersion = (version & 0XFF << 16) >> 16;
        int lowVersion = version & 0XFF;

        System.out.println("firstVersion:" + firstVersion);
        System.out.println("secondVersion:" + secondVersion);
        System.out.println("lowVersion:" + lowVersion);
    }

    public static void getPresetList(int userId) {
        HCNetSDK.NET_DVR_PRESET_NAME[] presetNames = new HCNetSDK.NET_DVR_PRESET_NAME[HCNetSDK.MAX_PRESET_V30];
        for (int i = 0; i < presetNames.length; i++) {
            presetNames[i] = new HCNetSDK.NET_DVR_PRESET_NAME();
            presetNames[i].dwSize = presetNames[i].size();
            presetNames[i].write();
        }
        Pointer loOutBuffer = new Memory((long) presetNames.length * presetNames[0].size());
        int dwOutBufferSize = presetNames.length * presetNames[0].size();
        IntByReference lpBytesReturned = new IntByReference(0);
        boolean presetList = hCNetSDK.NET_DVR_GetDVRConfig(userId, HCNetSDK.NET_DVR_GET_PRESET_NAME, 1, loOutBuffer, dwOutBufferSize, lpBytesReturned);
        if (!presetList) {
            System.out.println("获取预置点数据失败，错误代码：" + TestDemo.hCNetSDK.NET_DVR_GetLastError() + " " + hCNetSDK.NET_DVR_GetErrorMsg(lpBytesReturned));
        } else {
            ByteBuffer byteBuffer = loOutBuffer.getByteBuffer(0, lpBytesReturned.getValue());
            byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
            for (int i = 0; i < HCNetSDK.MAX_PRESET_V30; i++) {
                try {
                    StringBuilder presetName = new StringBuilder();
                    HCNetSDK.NET_DVR_PRESET_NAME presetNameStruct = new HCNetSDK.NET_DVR_PRESET_NAME();
                    presetNameStruct.dwSize = byteBuffer.getInt();
                    presetNameStruct.wPresetNum = byteBuffer.getShort();
                    byteBuffer.get(presetNameStruct.byRes1);
                    byteBuffer.get(presetNameStruct.byName);
                    presetNameStruct.wPanPos = byteBuffer.getShort();
                    presetNameStruct.wTiltPos = byteBuffer.getShort();
                    presetNameStruct.wZoomPos = byteBuffer.getShort();
                    byteBuffer.get(presetNameStruct.byRes);
                    if (presetNameStruct.wPresetNum != 0) {

                        if ((int) presetNameStruct.wPanPos != 0 && (int) presetNameStruct.wTiltPos != 0) {
                            presetName.append(new String(presetNameStruct.byName, "GBK").trim());
                            LogManager.getInstance().appendLog("预置位：" + presetNameStruct.wPresetNum + " 名称：" + presetName + " 水平参数：" + presetNameStruct.wPanPos + " 垂直参数：" + presetNameStruct.wTiltPos + " 变倍参数：" + presetNameStruct.wZoomPos);
                            System.out.println("预置位：" + presetNameStruct.wPresetNum + " 名称：" + presetName + " X：" + presetNameStruct.wPanPos + " Y：" + presetNameStruct.wTiltPos + " Z：" + presetNameStruct.wZoomPos);
                        } else { // 过滤掉
//                            presetName.append("预置点").append(presetNameStruct.wPresetNum);
                        }
                    }
                } catch (Exception e) {
                    System.out.println("报错了：" + e.getMessage());
                }
            }
        }
    }

    public static void getPtzPosition(int userId) {
        try {
            HCNetSDK.NET_DVR_PTZPOS ptzpos = new HCNetSDK.NET_DVR_PTZPOS();
            IntByReference retLen = new IntByReference(0);
            boolean result = hCNetSDK.NET_DVR_GetDVRConfig(userId, HCNetSDK.NET_DVR_GET_PTZPOS, 1, ptzpos.getPointer(), ptzpos.size(), retLen);
            if (!result) {
                System.out.println("获取PTZ失败，错误码：" + hCNetSDK.NET_DVR_GetLastError() + " " + hCNetSDK.NET_DVR_GetErrorMsg(retLen));
            } else {
                ptzpos.read();
                int pan = ptzpos.wPanPos;
                int tilt = ptzpos.wTiltPos;
                int zoom = ptzpos.wZoomPos;
                LogManager.getInstance().appendLog("当前的PTZ坐标：X：" + handlePtzNum(pan) + " " + "Y：" + handlePtzNum(tilt) + " " + "Z：" + handlePtzNum(zoom));
                System.out.println("当前的PTZ坐标：");
                System.out.println("水平位置：" + handlePtzNum(pan));
                System.out.println("垂直位置：" + handlePtzNum(tilt));
                System.out.println("变焦位置：" + handlePtzNum(zoom));
            }
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

    private static Integer handlePtzNum(int num) {
        return Integer.parseInt(Integer.toHexString(num));
    }
}
